package org.ssssssss.magicapi.ws;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.ssssssss.magicapi.Const;
import org.ssssssss.magicapi.core.service.MagicAPIService;
import org.ssssssss.magicapi.utils.JsonUtils;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsResponse;
import org.tio.websocket.common.WsSessionContext;
import org.tio.websocket.server.handler.IWsMsgHandler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;

/**
 * @author zcg
 * 2020年6月28日 下午5:32:38
 */

public class R2rWsMsgHandler implements IWsMsgHandler {
	private static Logger logger = LoggerFactory.getLogger(R2rWsMsgHandler.class);
		
	public static final R2rWsMsgHandler me = new R2rWsMsgHandler();

	public R2rWsMsgHandler() {
		
	}

	/**
	 * 握手时走这个方法，业务可以在这里获取cookie，request参数等
	 */
	@Override
	public HttpResponse handshake(HttpRequest request, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
		String clientip = request.getClientIp();
		String user = request.getParam("name");
		Tio.bindUser(channelContext, user);
		Tio.bindToken(channelContext, request.getParam("token"));
		logger.info("收到来自{}-{}的ws握手包\r\n{}", clientip, user, request.toString());
		//用tio-websocket，服务器发送到客户端的Packet都是WsResponse
		String msg = "收到来自"+clientip+"-"+user+"的ws握手包"+request.toString();
		WsResponse wsResponse = WsResponse.fromText(msg, R2rWsServerConfig.CHARSET);
		Tio.sendToGroup(channelContext.tioConfig, Const.GROUP_ID, wsResponse);
		return httpResponse;
	}

	/** 
	 * @param httpRequest
	 * @param httpResponse
	 * @param channelContext
	 * @throws Exception
	 * @author zcg
	 */
	@Override
	public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
		//绑定到群组，后面会有群发
		Tio.bindGroup(channelContext, Const.GROUP_ID);
		int count = Tio.getAll(channelContext.tioConfig).getObj().size();

		String msg = "{name:'" + channelContext.userid + "',message: '进来了，共【" + count + "】人在线" + "'}";
		//用tio-websocket，服务器发送到客户端的Packet都是WsResponse
		WsResponse wsResponse = WsResponse.fromText(msg, R2rWsServerConfig.CHARSET);
		//群发
		Tio.sendToGroup(channelContext.tioConfig, Const.GROUP_ID, wsResponse);
	}

	/**
	 * 字节消息（binaryType = arraybuffer）过来后会走这个方法
	 */
	@Override
	public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
		String method = "GET";
        Map<String, Object> params = new HashMap<>();
        params.put("bytes",bytes);
        params.put("context",channelContext);
        Const.getService().execute(method, Const.WS_BYTE_API, params);
		return null;
	}

	/**
	 * 当客户端发close flag时，会走这个方法
	 */
	@Override
	public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
		String method = "GET";
        Map<String, Object> params = new HashMap<>();
        params.put("bytes",bytes);
        params.put("context",channelContext);
        Const.getService().execute(method, Const.WS_CLOSE_API, params);		
		Tio.remove(channelContext, "receive close flag");
		return null;
	}

	/*
	 * 字符消息（binaryType = blob）过来后会走这个方法
	 */
	@Override
	public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
		WsSessionContext wsSessionContext = (WsSessionContext) channelContext.get();
		HttpRequest httpRequest = wsSessionContext.getHandshakeRequest();//获取websocket握手包
		if (logger.isDebugEnabled()) {
			logger.warn("握手包:{}", httpRequest);
		}
        
		String msg = "";
		String method = "GET";
        Map<String, Object> params = new HashMap<>();
		try {
			JSONObject jo = JSON.parseObject(text);
			WsResponse wsResponse;
			String type = jo.getString("type");
			if("magic".equals(type)) {
				MagicAPIService service = Const.getService();
				if(service!=null) {
					String path = jo.getString("api");
					method = jo.getString("method");
					String paramsStr = jo.getString("params");
					if(paramsStr==null) {
						paramsStr = "{}";
					}
			        params = 
			        		JSON.parseObject(paramsStr,new TypeReference<Map<String,Object>>(){});
			        if(path==null||method==null) {
			        	msg = "发送的请求必须包含api和method属性！";
			        }
			        else {
						Object result = service.execute(method, path, params);
				        if(result!=null) {
				        	msg = JSON.toJSON(result).toString();
				        	logger.info("执行接口返回:{}", msg);		
				        }
				        else {
				        	msg = "调用接口返回NULL:"+path;
				        }		        	
			        }
				}
				else {
					logger.error("网络服务：@Autowired MagicAPIService ERR");
					msg = "调用magic-api失败";
				}
				wsResponse = WsResponse.fromText(msg, Const.CHARSET);
				Tio.bSend(channelContext, wsResponse);				
			}
			else if("redis".equals(type)) {
				wsResponse = WsResponse.fromText(text, Const.CHARSET);
				Tio.sendToGroup(channelContext.tioConfig, Const.GROUP_ID, wsResponse);//群发
			}
			else {
		        params.put("text",text);
		        params.put("context",channelContext);
		        Const.getService().execute(method, Const.WS_TEXT_API, params);					
			}
		}
		catch(Exception e) {// 其他请求让外部去处理
	        params.put("text",text);
	        params.put("context",channelContext);
	        Const.getService().execute(method, Const.WS_TEXT_API, params);
			//logger.warn("数据处理异常:{}-{}-{}",channelContext.getClientNode().getIp(),text,e.getMessage());
		}
		return null;
	}
}
